package com.apimarket.util.net;

import com.apimarket.enums.NetContextEnum;
import com.apimarket.exception.NetContextException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;

//这个类用于用post的方式发送请求
public class PostJsonNetContext extends NetContext {
    //CloseableHttpClient可以理解为http客户端
    private CloseableHttpClient client;

    private HttpPost httpPost;

    protected static final int SUCCESS_CODE = 201;

    public PostJsonNetContext(String url, Map<String, Object> params) {
        super(url, params);
        //获得http客户端
        this.client = HttpClients.createDefault();
        //创建post请求
        this.httpPost = new HttpPost(getUrl());
    }

    //CloseableHttpResponse是响应模型
    protected CloseableHttpResponse getResponse() throws IOException {
        //这一步主要是给httpPost请求设置他的传入参数
        setJsonStyle(httpPost);
        //客户端执行发送post请求
        return client.execute(httpPost);
    }

    @Override
    public JsonNode getResultJson() throws IOException, URISyntaxException {
        /*
        资源是指在程序完成后必须关闭的流对象
        程序里打开的文件IO资源不属于内存里的资源，垃圾回收机制无法回收该资源，所以需要显示的关闭IO资源。
        JAVA7改写了所有的IO资源类，它们都实现了AutoCloseable接口，
        因此都可通过自动关闭资源的Try语句来关闭这些IO流。
         */
        try (CloseableHttpResponse response = getResponse()) {
            int statusCode = response.getStatusLine().getStatusCode();
            //从模型中获取响应实体
            HttpEntity entity = response.getEntity();
            String jsonStr = getJsonStr(entity);
            //HttpEntity代表底层流的基本实体
            //对于流实体资源的使用后要回收资源，用这个方法可以关闭资源
            EntityUtils.consume(entity);
            if (statusCode == SUCCESS_CODE) {
                //ObjectMapper提供的readTree，返回JsonNode对象
                return new ObjectMapper().readTree(jsonStr);
            } else {
                logger.error(jsonStr);
                throw new NetContextException(NetContextEnum.INSERT_ERROR);
            }
        }
    }
}
